7系列
7.0
1. 标量类型和返回类型声明
php7之前的版本,我们要想限定一个函数的参数的类型,只有array或者class两种。
标量类型声明有两种模式: 强制(默认)和严格模式。
类型参数:字符串(string), 整数(int), 浮点数 (float), 以及布尔值 (bool)
// 限制参数为int或string类型整型, 限制返回类型为int
function sumInt(int $a, int $b): int
{
return $a + $b;
}
echo sumInt(1, 1); // 2
echo sumInt('1', '1'); // 2
echo sumInt('1a', 'a1'); // error, 必须整型
严格模式
强制当前文件下的程序遵循严格的函数传参类型和返回类型,类型不匹配就会抛出错误。
declare(strict_types=1); // 开启严格模式
// 限制参数为int
function sum(int $a, int $b)
{
echo $a + $b;
}
sum(1, 1); // 2
sum('1', '1'); // error, 必须int
sum('1a', 'a1'); // error, 必须int
2. 三元表达式null合并
如果变量存在且值不为NULL,它就会返回自身的值,否则返回它的第二个操作数。
// 旧式
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// 新式
$username = $_GET['user'] ?? 'nobody';
3. 太空船操作符(组合比较符)
echo 1 <=> 2; // -1
echo 1 <=> 1; // 0
echo 2 <=> 1; // 1
4. use批量声明
use 可以在一句话中声明多个类或函数const了
但还是要写出每个类或函数或 const 的名称(并没有像 python 一样的 from some import * 的方法)
use some/namespace/{ClassA, ClassB, ClassC as C};
use function some/namespace/{fn_a, fn_b, fn_c};
use const some/namespace/{ConstA, ConstB, ConstC};
5. 定义常量数组
Array 类型的常量现在可以通过 define() 来定义。在 PHP5.6 中仅能通过 const定义。
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[0]; // dog
const WORD = [
'a',
'b',
'c'
];
echo WORD[1]; // b
6. 匿名类
现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
interface Logger
{
public static function log(string $msg);
}
$app = new class implements Logger {
public static function log(string $msg)
{
echo $msg;
}
};
$app::log('hello'); // hello
7. 闭包 Closure::call()
现在有着更好的性能,简短干练的暂时绑定一个方法到对象上闭包并调用它。
class A
{
private $x = 'hello';
}
// #1 PHP7之前版本的代码
$a = function () {
return $this->x;
};
// 中间层闭包,返回closure
$b = $a->bindTo(new A(), 'A');
echo $b(); // hello
----------------------------------------------------------------
// #2 PHP7+及更高版本的代码
$getX = function ($num) {
$this->x = 'world';
++$num;
return [$this->x, $num];
};
// 返回闭包的返回值
$ret = $getX->call(new A, 1);
print_r($ret);
/*
Array
(
[0] => world
[1] => 2
)
*/
8. 生成器可以返回表达式
此特性基于 PHP 5.5 版本中引入的生成器特性构建的。 它允许在生成器函数中通过使用 return语法来返回一个表达式(但是不允许返回引用值),可以通过调用 Generator::getReturn() 方法来获取生成器的返回值,但是这个方法只能在生成器完成产生工作以后调用一次。
$gen = (function () {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL; // 1 2
}
echo $gen->getReturn(), PHP_EOL; // 3
生成器中引入其他生成器
function gen2()
{
yield 3;
yield 4;
}
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
foreach (gen() as $v) {
echo $v, PHP_EOL;
}
/*
1
2
3
4
*/
9. intdiv()
整数的除法
echo 10 / 3, PHP_EOL; // 3.3333333333333
echo intdiv(10, 3), PHP_EOL; // 3
10. session_start()
可以接受一个 array 作为参数
// 设置session配置参数
session_start([
'cache_limiter' => 'private', // cache_limiter设置为私有的
'read_and_close' => true,
]);
11. unserialize()
过滤
class MyInfo
{
public function getMyName()
{
return 'hello';
}
}
$hello = new MyInfo();
$one = serialize($hello);
// 参数allowed_classes 设置为 true,表示允许解析class
$two = unserialize($one, ['allowed_classes' => true]);
// 参数allowed_classes 设置为 false,表示不允许解析class
$three = unserialize($one, ['allowed_classes' => false]);
// 不加参数。正常解析。
$four = unserialize($one);
// 只允许解析 类 MyInfo1。
$five = unserialize($one, ['allowed_classes' => ['MyInfo1']]);
// 分别输出下 getMyName方法;
var_dump($one); // "O:6:"MyInfo":0:{}"
var_dump($two->getMyName()); // hello
var_dump($three->getMyName()); // error, 没权限解析
var_dump($four->getMyName()); // hello
var_dump($five->getMyName()); // error, 没权限解析
12. 新增函数
random_bytes() // 获取加密安全的随机字节
random_int() // 获取生成加密安全、均匀分布的整数
$bytes = random_bytes(5);
// bin2hex 二进制字符串转换为十六进制值
echo bin2hex($bytes), PHP_EOL; // f392497a19
echo random_int(10,100), PHP_EOL; // 66
13. ??、?:
$a ?? 0 // 等同于 isset ($a) ? $a : 0
$a ?: 0 // 等同于 $a ? $a : 0
7.1
1.可为空(Nullable)类型
参数和返回值的类型声明可以通过在类型名称前添加一个问号(?)来标记为空(null)。表明函数参数或者返回值的类型要么为指定类型,要么为 null。
# eq1
function testReturn(?string $name)
{
return $name;
}
var_dump(testReturn('riven')); // string(6) "riven"
var_dump(testReturn(null)); // NULL
var_dump(testReturn2()); // Fatal error: Uncaught Error: Call to undefined function testReturn2()
# eq2:如果加了? 要么返回 string ,要么返回null。不能啥也不返还。会报错。
function testReturn3(): ?string
{
//return "abc";
//return null;
}
var_dump(testReturn3());
// Fatal error: Uncaught TypeError: Return value of testReturn3() must be of the type string or null
2.void返回类型
PHP7.0 添加了指定函数返回类型的特性,但是返回类型却不能指定为 void,7.1 的这个特性算是一个补充。定义返回类型为 void 的函数不能有返回值,即使返回 null 也不行:
#1
function testReturn4(): void
{
// 1. 要么啥都不返还 ok
// 2. 要么只return; ok
// return;
// 3. return null 也会报错
// return null;
// 4. return 4 会报错
// return 4;
}
#2 还有就是,void 只能用于返回值,不能用于参数中。比如下面的会报错:
function testReturn6(void $a) : void{}
var_dump(testReturn6()); // Fatal error: void cannot be used as a parameter type
#3 如果在类的继承中,申明为void返回类型的方法,子类要是继承重写,也只能返回void, 否则会触发错误:
class Foo
{
public function bar(): void
{
}
}
class Foobar extends Foo
{
// 覆盖失败
public function bar(): array
{
// Fatal error: Declaration of Foobar::bar(): array must be compatible with Foo::bar(): void
}
}
# 所以,你必须这样,就不会报错:
class Foo
{
public $a;
public function bar(): void
{
$this->a = 2;
}
}
class Foobar extends Foo
{
// 覆盖成功
public function bar(): void
{
$this->a = 3;
}
}
3.list 的方括号([])简写以及增加指定key
#1
$data = [
[1, 'Tom'],
[2, 'Fred'],
];
foreach ($data as [$id, $name]) {
echo $id, '-', $name, PHP_EOL;
}
// 1-Tom
// 2-Fred
#2 针对索引数组,还可以指定 key
$data = [
['id' => 1, 'name' => 'Tom'],
['id' => 2, 'name' => 'Fred'],
];
foreach ($data as ['id' => $id, 'name' => $name]) {
echo $id, '-', $name, PHP_EOL;
}
// 1-Tom
// 2-Fred
3.类常量可见范围设定
class ConstDemo
{
// 常量默认为 public
const PUBLIC_CONST = 0;
// 可以自定义常量的可见范围
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
// 多个常量同时声明只能有一个属性
private const FOO = 1, BAR = 2;
}
4.支持负的字符串偏移(字符串直接取)
var_dump('abcdef'[2]); // c
var_dump('abcdef'[-2]); // e
var_dump(strpos('aabbcc', 'b', -3)); // 3
5.多条件 catch
# before:在以往的 try … catch 语句中,每个 catch 只能设定一个条件判断
try {
// Some code...
} catch (ExceptionType1 $e) {
// 处理 ExceptionType1
} catch (ExceptionType2 $e) {
// 处理 ExceptionType2
} catch (Exception $e) {
// ...
}
# after:现在可以多个一起处理。用”|” 分割。
try {
// Some code...
} catch (ExceptionType1 | ExceptionType2 $e) {
// 对于 ExceptionType1 和 ExceptionType2 的处理
} catch (Exception $e) {
// ...
}